import { fromArrayBuffer } from 'geotiff';
import Image from "ol/layer/Image";
import ImageStatic from "ol/source/ImageStatic";
import Map from "ol/Map";
import { transformExtent, fromLonLat, transform } from "ol/proj";
import ImageCanvas  from "ol/source/ImageCanvas";
import ImageLayer from 'ol/layer/Image';

/**
 * 灰度图映射类  正在开发
 */

export default class WebGLMap {
  private gl: WebGLRenderingContext;
  constructor(private map: Map) { }
  private colorMap: Array<any>
  /**
   * 加载tiff
   * @param url tif文件路径
   * @returns tif文件宽高，像素点
   */
  async loadTiff(url: string, colorMap: Array<any>) {

    this.colorMap = colorMap
    const response = await fetch(url);
    const arrayBuffer = await response.arrayBuffer();
    const tiff = await fromArrayBuffer(arrayBuffer);
    const image = await tiff.getImage();
    const data = await image.readRasters();
    // 重新映射像素
    const mappedData = this.mapPixels(data, image.getWidth(), image.getHeight());
    const boundingBox = image.getBoundingBox();
    return this.mapColor(mappedData, image.getWidth(), image.getHeight(), boundingBox)
  }

  // 像素映射函数
  mapPixels(pixels, width, height) {
    const mappedPixels = new Uint8ClampedArray(width * height * 4); // RGBA
    const numColors = this.colorMap.length;

    pixels.forEach(pixel => {
      for (let i = 0; i < pixel.length; i++) {
        const value = pixel[i];
        let color = [0, 0, 0, 0]; // 默认透明色

        // 根据颜色映射数组查找相应颜色
        for (let j = 0; j < numColors; j++) {
          if (value <= this.colorMap[j][0]) {
            color = this.colorMap[j][1];
            break;
          }
        }

        // 设置 RGBA 值
        mappedPixels[i * 4] = color[0];      // R
        mappedPixels[i * 4 + 1] = color[1];  // G
        mappedPixels[i * 4 + 2] = color[2];  // B
        mappedPixels[i * 4 + 3] = color[3] * 255; // A (乘以 255)
      }
    });


    return mappedPixels;
  };

  /**
   * 映射到新图层
   * @param mappedData 
   * @param width 
   * @param height 
   * @param boundingBox 
   */
  mapColor(mappedData: any, width: number, height: number, boundingBox: any) {
    // 创建一个 canvas
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d');

    // 将 mappedData 绘制到 canvas 上
    const imageData = new ImageData(mappedData, width, height);
    ctx.putImageData(imageData, 0, 0);
    const transformedBoundingBox = transformExtent([-180, -80.9, 180, 80.9], 'EPSG:4326', 'EPSG:3857');
    // debugger
    // 将 canvas 转换为 Data URL
    const imageUrl = canvas.toDataURL();

    // 创建静态图层
    const rasterLayer = new Image({
      source: new ImageStatic({
        url: imageUrl,
        imageExtent: transformedBoundingBox, // 根据数据范围设置
        projection: 'EPSG:3857'
      }),
      zIndex: 2,
      opacity: 0.6
    });
    return rasterLayer
    // this.map.addLayer(rasterLayer);
  }


  //  测试  使用webgl 进行流式刷新**********************

  /**
   * 创建顶点和片源着色器  测试阶段
   * 
   */
  createVertex_Fragment(): any {
    const canvas = document.createElement('canvas');
    // 设置画布大小
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    this.gl = canvas.getContext('webgl')
    // 顶点着色器
    const vertexShaderSource = `
        attribute vec2 a_position;
        void main() {
          gl_Position = vec4(a_position,0,1);
        }
     `;

    const fragmentShaderSource = `
         precision mediump float;  // 默认精度为中精度 、 highp高精度、lowp 低精度
         uniform vec4 u_color;  // 定义在整个渲染过程中保持不变的变量
         void main() {
            gl_FragColor = u_color;
         }
      `;
    return { vertexShaderSource, fragmentShaderSource }
  }

  /**
   * 编译着色器
   * @param source 
   * @param type 
   */
  compileShader(source: any, type: any) {
    const shader = this.gl?.createShader(type);  // 创建着色器
    // 确保shader不是null或undefined
    if (shader) {
      this.gl.shaderSource(shader, source); // 绑定着色器资源
      this.gl.compileShader(shader);   // 编译着色器

      if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
        console.error('Error compiling shader:', this.gl.getShaderInfoLog(shader));
        this.gl.deleteShader(shader);
        return null;
      }
    } else {
      console.error('Failed to create shader: WebGLShader is null or undefined');
    }

    return shader;
  }

  /**创建程序 */
  createProgram() {
    // 获取顶点、片源
    const vertex_fragment = this.createVertex_Fragment();

    // 创建程序
    const vertexShader = this.compileShader(vertex_fragment.vertexShaderSource, this.gl.VERTEX_SHADER)
    const fragmentShader = this.compileShader(vertex_fragment.fragmentShaderSource, this.gl.FRAGMENT_SHADER)
    const program = this.gl.createProgram();
    // 附上着色器
    if (program && vertexShader && fragmentShader) {
      this.gl.attachShader(program, vertexShader)
      this.gl.attachShader(program, fragmentShader)
      this.gl.linkProgram(program)
      this.gl.useProgram(program)
    }
    return program;
  }

  /** 创建缓冲区 */
  createBuffer() {
    const positionBuffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, positionBuffer)

    // 获取程序
    const program = this.createProgram()
    // 连接属性  -- 位置定位
    if (program) {
      const positionLocation = this.gl.getAttribLocation(program, 'a_position')
      this.gl.enableVertexAttribArray(positionLocation) //WebGL 将开始从与该索引关联的缓冲区对象中读取顶点数据，并在后续的绘制操作中使用这些数据
      this.gl.vertexAttribPointer(positionLocation, 2, this.gl.FLOAT, false, 0, 0)  // 绑定

      // 设置颜色
      const colorLocation = this.gl.getUniformLocation(program, 'u_color')
      // 执行渲染
      this.render(colorLocation)

    }

  }

  /** 更新数据 */
  updateData(data: Array<any>) {
    // 假设 data 是一个数组，包含顶点坐标
    this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(data), this.gl.STATIC_DRAW)
  }

  /** webgl渲染 */
  render(colorLocation: any) {
    // 清除画板
    this.gl.clearColor(0, 0, 0, 0)
    // 清除缓冲区
    this.gl.clear(this.gl.COLOR_BUFFER_BIT)

    // 绘制
    this.gl.uniform4f(colorLocation, Math.random(), Math.random(), Math.random(), 1) // 随机颜色
    this.gl.drawArrays(this.gl.POINTS, 0, 100); // 假设有100个点

  }

}